package com.whenjun.common;

import cn.dev33.satoken.exception.SaTokenException;
import com.ifootbook.util.FootBookException;
import com.ifootbook.util.HttpUtil;
import com.ifootbook.util.common.CallResult;
import com.ifootbook.util.common.Constants;
import com.whenjun.entity.Request;
import com.whenjun.service.IRequestService;
import com.whenjun.util.SaTokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Auther: whenjun
 * @Date: 2023/6/5 0005 18:05
 * @Description:
 */
@ResponseBody
@ControllerAdvice
public class GlobalExceptionHandler extends LoggerParent {

    @Autowired
    private IRequestService requestService;

    // 全局异常拦截（拦截项目中的NotLoginException异常）
    @ExceptionHandler(SaTokenException.class)
    public CallResult<?> handlerNotLoginException(SaTokenException saTokenException, HttpServletRequest request,
        HttpServletResponse response) throws Exception {

        // 打印堆栈，以供调试
        saTokenException.printStackTrace();

        // 判断场景值，定制化异常信息

        FootBookException footBookException = new FootBookException();
        footBookException.setErrorCode(100);
        footBookException.setMsg("token:" + saTokenException.getMessage());

        // 返回给前端
        return footBookException.getCallResult();
    }

    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public CallResult<?> methodArgumentNotValidException(HttpServletRequest request,
        MethodArgumentNotValidException exception) throws Exception {
        String requestId = SaTokenUtil.getRequestId();
        log.error("requestId:" + requestId + "," + exception.getMessage());

        List<ObjectError> allErrors = exception.getBindingResult().getAllErrors();
        String message = allErrors.stream().map(s -> s.getDefaultMessage()).collect(Collectors.joining(";"));

        Request requestBean = new Request();
        requestBean.setId(requestId);
        requestBean.setException(message);

        requestService.updateById(requestBean);
        return new CallResult<>(Constants.DEFAULT_RETURN_CODE, message);
    }

    @ExceptionHandler(value = FootBookException.class)
    public CallResult<?> footbookException(HttpServletRequest request, FootBookException exception) throws Exception {
        String requestId = SaTokenUtil.getRequestId();
        log.error("requestId:" + requestId + "," + exception.getMessage());
        Request requestBean = new Request();
        requestBean.setId(requestId);
        requestBean.setException(exception.getMessage());
        requestService.updateById(requestBean);
        return exception.getCallResult();
    }

    @ExceptionHandler(value = Exception.class)
    public CallResult<?> allExceptionHandler(HttpServletRequest request, Exception exception) throws Exception {
        exception.printStackTrace();

        String requestId = SaTokenUtil.getRequestId();

        log.error("requsetId:{}," + exception.getMessage(), requestId);
        HttpUtil.printRequest(request);
        Request requestBean = new Request();
        requestBean.setId(requestId);
        requestBean.setException(exception.getMessage());
        requestService.updateById(requestBean);
        return new CallResult<>(Constants.SYSTEM_RETURN_CODE, Constants.SYSTEM_RETURN_MESSAGE);
    }

    @ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
    public CallResult<?> RequestMethodNotSupportedException(HttpServletRequest request,
        HttpRequestMethodNotSupportedException exception) {
        String msg = exception.getMessage().replace("\'", "");
        log.error(msg.replace("\"", ""));
        HttpUtil.printRequest(request);
        String requestId = SaTokenUtil.getRequestId();
        log.error("requestId:" + requestId + "," + exception.getMessage());
        Request requestBean = new Request();
        requestBean.setId(requestId);
        requestBean.setException(exception.getMessage());
        requestService.updateById(requestBean);
        return new CallResult<>(Constants.SYSTEM_RETURN_CODE, msg);
    }

    @ExceptionHandler(value = HttpMessageNotReadableException.class)
    public CallResult<?> messageNotReadableException(HttpServletRequest request,
        HttpMessageNotReadableException exception) {
        String requestId = SaTokenUtil.getRequestId();
        log.error("requestId:" + requestId + "," + exception.getMessage());
        Request requestBean = new Request();
        requestBean.setId(requestId);
        requestBean.setException(exception.getMessage());
        requestService.updateById(requestBean);
        return new CallResult<>(Constants.SYSTEM_RETURN_CODE, exception.getMessage());
    }
}
